/* eslint-disable react/no-did-update-set-state */
import React from 'react';
import ReactEcharts from 'echarts-for-react';
import {
  Card, Button, Modal, Input, message,
} from 'antd';
import { cloneDeep } from 'lodash';
import { reverse } from 'lodash/fp';
import { historyTask } from 'services/history';
import { sendMessage } from 'services/process';
import { getToken, getUserId } from 'services/token';
import timeFormat from 'utils/time';
import mapNames from 'assets/Visualization.json';
import { defaultRejectHandler } from 'utils/http';


const { TextArea } = Input;

const processStatus = {
  UNSTART: 0,
  RUN: 1,
  FINISHED: 2,
  ERROR: 3,
};

export default class Chart extends React.Component {
  constructor() {
    super();
    this.dataSource = undefined;
    this.timer = undefined;
    this.gaugeList = undefined;
    this.inputRef = undefined;
    this.state = {
      showModal: false,
      lineOption: {},
      gaugeOption: {},
      instanceId: '',
      gaugeHeight: '400px',
      chartVisible: true,
    };
  }


  componentDidUpdate(prevProps) {
    const { chosenTask, id } = this.props;
    if (chosenTask !== prevProps.chosenTask) {
      if (this.timer) clearInterval(this.timer);
      this.dataSource = undefined;
      this.updateChart(chosenTask, id);
    }
  }

  componentWillUnmount() {
    if (this.timer) { clearInterval(this.timer); }
  }

  updateChart = async (taskId, id) => {
    try {
      const data = await historyTask({
        params: {
          taskId,
          historyId: id,
        },
      });
      this.setState({ instanceId: data.instance });
      // console.log(data);
      switch (data.taskStatus) {
        case processStatus.UNSTART:
          this.setState({ chartVisible: false });
          message.info('当前任务未执行');
          break;
        case processStatus.RUN:
          if (data.arguments.length !== 0) {
            this.setState({ chartVisible: true });
            this.loadChart(data.arguments);
            this.timer = setInterval(
              () => {
                historyTask({
                  params: {
                    taskId,
                    historyId: id,
                  },
                }).then((newData) => {
                  if (newData.taskStatus === 2) {
                    this.dataSource = undefined;
                    this.loadChart(newData.arguments);
                    // clearInterval(this.timer);
                  } else {
                    this.loadChart(newData.arguments);
                  }
                }, defaultRejectHandler);
              }, 2000,
            );
          } else {
            this.setState({ chartVisible: false });
            message.info('无数据产生');
          }
          break;
        case processStatus.FINISHED:
          if (data.arguments.length !== 0) {
            this.setState({ chartVisible: true });
            this.loadChart(data.arguments);
            // clearInterval(this.timer);
          } else {
            this.setState({ chartVisible: false });
            message.info('无数据产生');
          }
          break;
        case processStatus.ERROR:
          this.setState({ chartVisible: false });
          message.error('任务异常');
          break;
        default:
          this.setState({ chartVisible: false });
          message.error('发生未知错误');
      }
    } catch (error) {
      console.error(error.message);
    }
  }


  loadChart = (data) => {
    // 0: (2) ["time", "2019-12-27 15:29:32"]
    // 1: (2) ["downLength", 2.302699285301835]
    // 2: (2) ["feedRate", 5.435733013644313]
    // 3: (2) ["forceX", 37.848237907321746]
    const reLineList = data.filter((item) => item.type === 'LineChart');
    let lineList = reLineList.map((item) => ({
      ...item,
      item: reverse(item.item),
    }));
    // 第一次
    if (this.dataSource === undefined) {
      // dataset第一行,时间戳
      const firstLine = [
        'time',
        ...lineList[0].item.map((j) => j.timeStamp).map(timeFormat),
      ];
      // dataset后几行，一行一条线
      const lineData = lineList.map(
        (item) => [
          mapNames[item.name].name,
          ...item.item.flatMap((j) => j.value.toFixed(2)),
        ],
      );
      this.lineLen = lineList.length;
      this.dataSource = [
        firstLine,
        ...lineData,
      ];
    } else {
      // 过滤掉重复值
      lineList = lineList.map((i) => ({
        ...i,
        item: i.item.filter((j) => !(this.dataSource[0].includes(timeFormat(j.timeStamp)))),
      }));

      const firstLine = lineList[0].item.map((j) => timeFormat(j.timeStamp));
      this.dataSource[0] = [...this.dataSource[0], ...firstLine];
      lineList.forEach((item) => {
        this.dataSource = this.dataSource.map((j) => {
          if (j[0] === mapNames[item.name].name) {
            const lineData = item.item.map((k) => k.value.toFixed(2));
            return [...j, ...lineData];
          }
          return j;
        });
      });
    }
    this.loadLineChart();
    // 仪表盘
    this.gaugeList = data.filter((item) => item.type === 'GaugeChart');
    this.gaugeLen = this.gaugeList.length;
    const height = `${(400 * parseInt((this.gaugeLen + 1) / 2, 0)).toString()}px`;
    this.setState({ gaugeHeight: height });
    this.loadGaugeChart();
  };


  sendMessage = () => {
    const { inputRef: { state: { value } }, state: { instanceId } } = this;
    const { name } = this.props;
    const userId = getUserId(getToken());
    const data = {
      from: userId,
      ecnId: instanceId,
      message: {
        process: name,
        device: instanceId,
        content: value,
      },
    };
    sendMessage(data).then(() => {
      message.success('消息已发送');
      this.setState({ showModal: false });
    }, defaultRejectHandler);
  }

  loadLineChart = () => {
    const option = {
      title: {
        text: '折线图',
      },
      dataset: { source: [] },
      tooltip: {
        trigger: 'axis',
        axisPointer: {
          type: 'cross',
          label: {
            backgroundColor: '#6a7985',
          },
        },
      },
      legend: {},
      grid: {
        left: '3%',
        right: '4%',
        bottom: '3%',
        containLabel: true,
      },
      dataZoom: [
        { // 这个dataZoom组件，默认控制x轴。
          type: 'slider', // 这个 dataZoom 组件是 slider 型 dataZoom 组件
          start: 10, // 左边在 10% 的位置。
          end: 60, // 右边在 60% 的位置。
        },
      ],
      xAxis: [
        {
          type: 'category',
        },
      ],
      yAxis: [
        {
          type: 'value',
        },
      ],
      series: [
      ],
    };
    const seriesItem = {
      type: 'line',
      seriesLayoutBy: 'row',
      markPoint: {
        data: [
          { type: 'max', name: '最大值' },
          { type: 'min', name: '最小值' },
        ],
      },
      markLine: {
        data: [
          { type: 'average', name: '平均值' },
        ],
      },
    };
    option.dataset.source = this.dataSource;
    for (let i = 0; i < this.lineLen; i += 1) { option.series.push(seriesItem); }
    this.setState({ lineOption: option });
  }

loadGaugeChart = () => {
  const { gaugeList } = this;
  const option = {
    title: {
      text: '',
      textStyle: {
        fontSize: 16,
      },
    },
    tooltip: {
      formatter: '{a} <br/>{b} : {c}%',
    },
    toolbox: {
      feature: {
        restore: {},
      },
    },
    series: [],
  };
  const seriesItem = {
    name: '',
    type: 'gauge',
    // 中心位置需要设置
    center: ['25%', '50%'],
    radius: '130px',
    detail: {
      formatter: '{value}',
      textStyle: {
        color: 'auto',
        fontSize: 16,
      },
      fontWeight: 'bolder',
      borderRadius: 20,
      backgroundColor: '#fff',
      borderColor: '#ffaa00',
      borderWidth: 4,
    },
    title: {
      // 其余属性默认使用全局文本样式，详见TEXTSTYLE
      fontWeight: 'bolder',
      fontSize: 16,
    },
    // data需要设置
    data: [],
    axisLine: {
      // 坐标轴线
      lineStyle: {
        width: 8,
      },
    },
    axisTick: {
      // 坐标轴小标记
      splitNumber: 10, // 每份split细分多少段
      length: 12, // 属性length控制线长
      lineStyle: {
        // 属性lineStyle控制线条样式
        color: 'auto',
      },
    },
    pointer: {
      width: 4,
    },
    axisLabel: {
      // 坐标轴文本标签
      textStyle: {
        color: 'auto',
        fontSize: 10,
      },
    },
    splitLine: {
      // 分隔线
      show: true,
      length: 16, // 属性length控制线长
      lineStyle: {
        // 长刻度线样式
        color: 'auto',
      },
    },
  };
  gaugeList.forEach((i, index) => {
    const item = cloneDeep(seriesItem);
    item.name = i.name;
    item.data = [{ value: i.item[0].value.toFixed(2), name: mapNames[i.name].name }];
    item.min = mapNames[i.name].min;
    item.max = mapNames[i.name].max;
    const y = parseInt(index / 2, 0);
    const x = index % 2;
    item.center[1] = `${(200 + 400 * y).toString()}px`;
    item.center[0] = `${(x * 50 + 25).toString()}%`;
    option.series.push(item);
  });
  this.setState({ gaugeOption: option });
}

render() {
  const {
    showModal, lineOption, gaugeOption, gaugeHeight, chartVisible,
  } = this.state;
  const { chosenTask } = this.props;
  return (
    <>
      {chartVisible
        ? (
          <Card
            hoverable
            title={`实时流程监控 ${chosenTask}`}
            style={{ margin: '30px auto' }}
            extra={<Button type="primary" onClick={() => this.setState({ showModal: true })}>发送消息</Button>}
          >
            <Card style={{ margin: 'auto' }} hoverable id="line">
              <ReactEcharts
                style={{ width: '800px', height: '400px', margin: 'auto' }}
                option={lineOption}
              />
            </Card>
            <Card style={{ margin: '30px auto' }} hoverable id="gauge">
              <ReactEcharts
                style={{ width: '800px', height: gaugeHeight, margin: 'auto' }}
                option={gaugeOption}
              />
            </Card>
          </Card>
        )
        : <></>}
      <Modal
        title="发送消息"
        visible={showModal}
        onOk={this.sendMessage}
        onCancel={() => { this.setState({ showModal: false }); }}
      >
        <TextArea
          rows={3}
          ref={(input) => { this.inputRef = input; }}
        />
      </Modal>
    </>
  );
}
}
